package com.alibaba.algo.aop;

import com.alibaba.algo.annotation.OperateLogAnnotation;
import com.alibaba.algo.cooperation.usercomponent.service.user.SysOperateLogService;
import com.alibaba.algo.cooperation.usercomponent.vo.req.SysOperateLogDTO;
import com.alibaba.fastjson.JSON;
import com.xxl.sso.core.conf.Conf;
import com.xxl.sso.core.user.XxlSsoUser;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.util.ObjectUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName: OperateLogAnnotation
 * @Description: 操作日志aop
 * @Author: wugongzi
 * @Date: 2021/12/02 16:07
 * @Version: 1.0
 */
@Configuration
@Aspect
@Order(1)
public class OperateLogAop {

    private static final Logger logger = LoggerFactory.getLogger(OperateLogAop.class);
    @Resource
    private SysOperateLogService sysOperateLogService;

    /**
     * 处理流程：
     * 读取注解中定义的资源名 和 操作
     * 读取参数中添加的用户信息
     * 插入操作日志表
     *
     * @param joinPoint
     * @param obj
     */
    @AfterReturning(returning = "obj", pointcut = "@annotation(com.alibaba.algo.annotation.OperateLogAnnotation)")
    public void afterReturning(JoinPoint joinPoint, Object obj) {
        logger.info("=====OperateLogAop Log start=====");
        // 获取注解中的信息
        String targetClass = joinPoint.getTarget().getClass().getName();
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        Object[] args = joinPoint.getArgs();
        List<Object> parameters = new ArrayList<>();
        for (Object arg : args) {
            if (!(arg instanceof HttpServletRequest) && !(arg instanceof HttpServletResponse) && !(arg instanceof MultipartFile)) {
                parameters.add(arg);
            }
        }
        OperateLogAnnotation operateLogAnnotation = method.getAnnotation(OperateLogAnnotation.class);

        SysOperateLogDTO sysOperateLogDTO = new SysOperateLogDTO();
        sysOperateLogDTO.setOperateType(operateLogAnnotation.operateType().getCode());
        sysOperateLogDTO.setResourceType(operateLogAnnotation.resouceType().getCode());
        sysOperateLogDTO.setResourceName(operateLogAnnotation.resouceType().getDsec());
        sysOperateLogDTO.setTargetClass(targetClass);
        sysOperateLogDTO.setTargetMethod(method.getName());
        sysOperateLogDTO.setTargetMethodParams(JSON.toJSONString(parameters));
        // 获取当前登录用户
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String creator = null;
        if (!ObjectUtils.isEmpty(request.getAttribute(Conf.SSO_USER))) {
            XxlSsoUser xxlSsoUser = (XxlSsoUser) request.getAttribute(Conf.SSO_USER);
            creator = xxlSsoUser.getUsername();
        }
        sysOperateLogDTO.setCreator(creator);
        sysOperateLogDTO.setGmtCreated(LocalDateTime.now());

        sysOperateLogService.insert(sysOperateLogDTO);
        logger.info("=====OperateLogAop Log end=====");
    }

    /**
     * 获取请求IP
     *
     * @param request
     * @return
     */
    public String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        String strUnKnown = "unknown";
        if (ip != null && ip.length() != 0 && !strUnKnown.equalsIgnoreCase(ip)) {
            // 多次反向代理后会有多个ip值，第一个ip才是真实ip
            String str = ",";
            if (ip.contains(str)) {
                ip = ip.split(",")[0];
            }
        }
        if (ip == null || ip.length() == 0 || strUnKnown.equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
            logger.info("Proxy-Client-IP ip: {}", ip);
        }
        if (ip == null || ip.length() == 0 || strUnKnown.equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
            logger.info("WL-Proxy-Client-IP ip: {}", ip);
        }
        if (ip == null || ip.length() == 0 || strUnKnown.equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
            logger.info("HTTP_CLIENT_IP ip: {}", ip);
        }
        if (ip == null || ip.length() == 0 || strUnKnown.equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            logger.info("HTTP_X_FORWARDED_FOR ip: {}", ip);
        }
        if (ip == null || ip.length() == 0 || strUnKnown.equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
            logger.info("X-Real-IP ip: {}", ip);
        }
        if (ip == null || ip.length() == 0 || strUnKnown.equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
            logger.info("getRemoteAddr ip: {}", ip);
        }
        logger.info("ip----:{} ", ip);
        return ip;
    }

}
